package Charm_Seq;

import java.io.*;  
import java.io.File;  
import java.io.FileReader;  
import java.io.IOException;
import java.nio.file.*;
import java.nio.charset.Charset;
import java.text.MessageFormat;  
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;  
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.*;


public class Main {
	int n1;
	int n2;
    int n3;
    String[] attrNames;
    String f10[];
    String s3[];
    int c[]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
    int f[]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
    int ml=0;
    int mc=0;
    int mf=0;
    double minSup;
        public static void main(String args[]){
                    
              String filePath="src/lib/input.txt";
              double minSup=0.1214;
              int hashTableSize=1000000;
              Context context=new Context();
              AlgoCharm_Bitset charm=new AlgoCharm_Bitset();
              Main demo = new Main();
              demo.readRDBMSData(filePath,context);		
              charm.runAlgorithm(context,minSup,hashTableSize);
              demo.printFItems(charm.closedItemsets,demo.n1,demo.n2,demo.n3,minSup);  
        }

         /** 
	         *读关系表中的数据，转化为事务数据 ，并导入context
	     *  
	     * @param filePath 
	     */  

        public  void readRDBMSData(String filePath,Context context) {  
	        String str;  
	        // 属性名称行 
	        String[] attrNames=null;
	        String[] temp;  
	        String[] newRecord;  
	        ArrayList<String[]> datas = null;
	        ArrayList<int[]> transactionDatas0;
	        ArrayList<String[]> transactionDatas;
	        double[] colArr0=null; //记录排序前的基因序列
	        double[] colArr1 = null; //记录排序后的基因序列
	        int[] colArr2=null;  //记录排序的序列编号
	        
	        datas = readLine(filePath);  
	        n3=datas.size()-1;
	        //  获取首行  
	        attrNames=datas.get(0); 
            n2=attrNames.length-1;//获取一行基因序列个数
	        transactionDatas0 = new ArrayList<>();
	        transactionDatas = new ArrayList<>();
	        System.out.println("将基因序列排序后输出：");
	        // 去除首行数据  
	        for (int i = 1; i < datas.size(); i++) {
	        	colArr0=new double[n2];
	            colArr1=new double[n2];
	            colArr2=new int[n2];
	            temp = datas.get(i); //获取文件一行数据保存到数组中 
	            //将数据复制到newRecord数组中
	            newRecord = new String[attrNames.length - 1]; 
	            System.arraycopy(temp, 0, newRecord, 0, attrNames.length-1);
	            //将newRecord数组中的基因，转换成double类型的数字保存到colArr数组中，用于后面比较大小
	            for (int j = 0; j < n2; j++) {  
	                double number=Double.parseDouble(newRecord[j]);
	            	colArr1[j]=number;
	            }
	           //将colArr1内容复制到colArr0中，保存未排序的基因序列数组
	            System.arraycopy(colArr1, 0, colArr0, 0, colArr1.length);
	            //将colArr1数组排序，这样就得到排序前的colArr0和排序后的colArr1
	            Arrays.sort(colArr1);
	            //将colArr1倒序
	            for(int z=0;z<n2;z++) {
	            	if(z>=n2-z-1) break;
	            	double tem=colArr1[z];
	            	colArr1[z]=colArr1[n2-z-1];
	            	colArr1[n2-z-1]=tem;
	            }
	            //将排序的序列保存到colArr2中（[2 1 0 3 4 ..]）
	            for(int g = 0; g < n2; g++) {
	               for(int h = 0; h < n2; h++) {
	            	  if (colArr1[g]== colArr0[h]) {
	            		  colArr2[g]=h;
	            		  break;
	            	  }
	               }
	            }  
	            
	            System.out.println(Arrays.toString(colArr1));
	            transactionDatas0.add(colArr2);
	        }
	        for(int[] seqInt :transactionDatas0) {
            	String[] seqStr=new String[n2];
            	for(int i=0;i<n2;i++) {
            		seqStr[i]=seqInt[i]+"";
            	}
            	transactionDatas.add(seqStr);
            }
	        System.out.println("将排序后的基因表达式转换成列标签：");
	        for(String [] a:transactionDatas) {
	        	System.out.println(Arrays.toString(a));
	        }
	        // 将事务数据转到context中做统一处理
	        for(int i=0;i<transactionDatas.size();i++){ 
	        		
                   context.addObject(transactionDatas.get(i));
            }
	     }  

         /** 
	         * 从文件中逐行读数据
	     *  
	     * @param filePath 
	         *  数据文件地址  
	     * @return 
	     */  	   
        private  ArrayList<String[]> readLine(String filePath) {  
	        File file = new File(filePath);  
	        ArrayList<String[]> dataArray = new ArrayList<String[]>();  
	        try {  
	            BufferedReader in = new BufferedReader(new FileReader(file));  
	            String str;  
	            String[] tempArray;  
	            while ((str = in.readLine()) != null) {  
	                tempArray = str.split(" ");  
	                dataArray.add(tempArray);  
	            }  
	            in.close();  
	        } catch (IOException e) {  
	            e.getStackTrace();  
	        }  
	        return dataArray;  
	    }

      


	    /** 
	     * 输出频繁闭合项集
	     */  
        private  void printFItems(Itemsets closedItemsets,int n1,int n2,int n3,double minSup) {  
	          
	       int l=closedItemsets.getLevels().size()-1;
	       System.out.println("支持度阈值："+minSup+"；实例数："+n3+"；属性数："+n2+ "；项数："+n1);
           for (int k=1; k<=l;k++){
              for(Itemset i:closedItemsets.getLevels().get(k)){
                 c[k-1]++;
                 if(i.cardinality>=f[k-1]){
                    f[k-1]=i.cardinality;
                 }
              }
              System.out.println(k+"项集：");
              System.out.println("数量："+c[k-1]+"；最大频次："+f[k-1]);
           }
           for (int k=1;k<=l;k++){
              ml=ml+k;  mc=mc+c[k-1];  mf=mf+f[k-1];
           }
           double ml1=(double)ml/l;
           double ml2=(double)ml1/n2;                          
           double mc1=(double)mc/l;
           double mc2=(double)mc1/n3;
           double mf1=(double)mf/l;
           double mf2=(double)mf1/n3;
           System.out.println("模式总数量："+mc);
           System.out.println("模式平均长度："+ml1+"；平均数量："+mc1+"；平均频次："+mf1);
           System.out.println("模式与实例长度比："+ml2+"；数量比："+mc2+"；频次比："+mf2);
           
            }
        
//        public String toString(){
//            StringBuilder sb = new StringBuilder();
//            for(Itemset it : objects)
//                sb.append(it).append("\n");
//            
//            return sb.toString();
//        }

  }




